package org.ricks.log.pattern;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chenwei
 * @Description:日志样式格式
 * @date 2023/1/918:30
 */
public class FormatterFactory {

    private static final Map<String, Class<? extends PatternFormatter>> formatterImplClassMap = new HashMap<>();

    static {
        // 日期
        formatterImplClassMap.put("date", DatePatternFormatter.class);

        // 等级
        formatterImplClassMap.put("level", LevelPatternFormatter.class);

        // 线程
        formatterImplClassMap.put("thread", ThreadPatternFormatter.class);

        // full class name
        formatterImplClassMap.put("class", FullClassNameToken.class);

        // method name
        formatterImplClassMap.put("method", MethodNameToken.class);

        // 内容
        formatterImplClassMap.put("msg", MsgPatternFormatter.class);

        // 换行
        formatterImplClassMap.put("n", LineSeparatorPatternFormatter.class);
    }

    /**
     * 根据配置格式化文本来构建格式器的具体实现列表
     *
     * @param pattern 格式化文本配置
     * @return 返回格式器列表
     */
    public static List<PatternFormatter> build(String pattern) {
        return PatternParser.parseFormatterList(pattern);
    }

    /**
     * 权限解析出来的配置创建格式化对象.
     *
     * @param id             格式化配置ID
     * @param formattingInfo 格式化信息
     * @param options        格式化对象可能需要的参数
     * @return 格式化实现对象
     */
    public static PatternFormatter create(String id, FormattingInfo formattingInfo, String options) {
        Class<?> klass = formatterImplClassMap.get(id);
        if (klass == null) {
            return new LiteralPatternFormatter(("[%" + id + "(unrealized)]").toCharArray());
        }

        try {
            Constructor<?> constructor = klass.getConstructor(FormattingInfo.class, String.class);
            return (PatternFormatter) constructor.newInstance(formattingInfo, options);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            return new LiteralPatternFormatter(("[%" + id + "(" + e.getMessage() + ")]").toCharArray());
        }
    }
}
